package com.filex.ads.interstitial;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.filex.ads.RequestParams;
import com.filex.ads.common.AdError;
import com.filex.ads.common.AdFormat;
import com.filex.ads.common.AdUrlGenerator;
import com.filex.ads.common.Preconditions;
import com.filex.ads.common.logging.Logger;
import com.filex.ads.common.utils.DeviceUtils;
import com.filex.ads.common.utils.Utils;
import com.filex.ads.network.AdLoader;
import com.filex.ads.network.AdRequest;
import com.filex.ads.network.AdResponse;
import com.filex.ads.network.FilexNetworkError;
import com.filex.ads.volley.VolleyError;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.ref.WeakReference;

import static com.filex.ads.common.CommonKeys.AD_RESPONSE_ADM_KEY;


public class FilexInterstitial implements IntersEventBroadcastReceiver.InternalAdListener {

    @NonNull private final WeakReference<Activity> mContextRef;
    @NonNull private String mPlacementId;

    @NonNull private InterstitialAdListener mAdListener = EMPTY_AD_LISTENER;

    @NonNull private AdLoader mInternalAdLoader;

    @NonNull private AdRequest mActiveRequest;

    @NonNull private final long mBroadCastEventId;

    @NonNull private String htmlResponse;

    @NonNull private IntersEventBroadcastReceiver mEventReceiver;

    @NonNull private int mAdWidth;

    @NonNull private int mAdHeight;

    public FilexInterstitial(@NonNull final Activity activity,
                             @NonNull final String placementId,
                             @NonNull final InterstitialAdListener adListener) {
        Preconditions.checkNotNull(activity, "Activity may not be null.");
        Preconditions.checkNotNull(placementId, "PlacementId may not be null.");
        Preconditions.checkNotNull(adListener, "InterstitialAdListener may not be null.");
        this.mContextRef = new WeakReference<>(activity);
        this.mPlacementId = placementId;
        this.mAdListener = adListener;
        mBroadCastEventId = Utils.generateUniqueId();
        mEventReceiver = new IntersEventBroadcastReceiver(this, mBroadCastEventId);
        mEventReceiver.register(mEventReceiver, activity.getApplicationContext());
    }

    public void loadAd() {
        internalLoad();
    }

    private void internalLoad() {
        Activity context = getContextOrDestroy();
        if (context == null) {
            Logger.d("Context may be destroy");
            return;
        }
        if (!DeviceUtils.isNetworkAvailable(context.getApplicationContext())) {
            Logger.d("Network Unavailable");
            return;
        }
        if (isLoading()) {
            Logger.d("Ad is loading for placement id : " + mPlacementId);
            return;
        }
        int currentOrientation = DeviceUtils.getScreenOrientation(context);
        boolean isPortrait = currentOrientation == ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
                || currentOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
        mAdWidth = isPortrait ? 320 : 480;
        mAdHeight = isPortrait ? 480 : 320;
        String requestUrl = new AdUrlGenerator(context.getApplicationContext())
                .withAdFormat(AdFormat.INTERSITITAL)
                .withRequestParams(new RequestParams.Builder().width(mAdWidth).height(mAdHeight).build())
                .generateUrlString(mPlacementId);
        if (mInternalAdLoader == null) {
            mInternalAdLoader = new AdLoader(requestUrl, AdFormat.INTERSITITAL, mPlacementId,
                    context, new AdLoader.Listener() {
                @Override
                public void onSuccess(AdResponse response) {
                    onAdLoadSuccess(response);
                }

                @Override
                public void onErrorResponse(VolleyError error) {
                    onAdLoadError(error);
                }
            });
        }
        mInternalAdLoader.loadAd();
    }


    void onAdLoadSuccess(@NonNull final AdResponse adResponse) {
        mActiveRequest = null;
        try {
            JSONArray jsonArray = adResponse.getJsonBody();
            JSONObject adJSONObject = jsonArray.getJSONObject(0);
            htmlResponse = adJSONObject.getString(AD_RESPONSE_ADM_KEY);
            mAdListener.onAdLoaded();
        } catch (Exception e) {
            e.printStackTrace();
            onAdLoadError(new VolleyError(e));
        }
    }

    void onAdLoadError(VolleyError error) {
        setNotLoading();
        mAdListener.onAdFailed(getAdErrorFromVolleyError(error));
    }

    private AdError getAdErrorFromVolleyError(@NonNull final VolleyError error) {
        if (error instanceof FilexNetworkError) {
            switch (((FilexNetworkError) error).getReason()) {
                case BAD_BODY:
                    return AdError.BAD_REQUEST;
                case NO_FILL:
                    return AdError.NO_FILL;
                default:
                    return AdError.UNSPECIFIED;
            }
        }
        if (error.networkResponse.statusCode >= 400) {
            return AdError.INTERNAL_ERROR;
        }
        return AdError.UNSPECIFIED;
    }


    public boolean isAdReady() {
        return false;
    }

    public boolean isLoading() {
        return mActiveRequest != null;
    }


    public void show() {
        Context context = getContextOrDestroy();
        if (context == null) {
            return;
        }
        if (!isAdReady()) {
            Logger.e("Interstitial Ad ");
        }
        InterstitialActivity.start(context, htmlResponse, mAdWidth, mAdHeight, mBroadCastEventId);
    }


    static final InterstitialAdListener EMPTY_AD_LISTENER = new InterstitialAdListener() {
        @Override
        public void onAdLoaded() {

        }

        @Override
        public void onAdFailed(AdError error) {

        }

        @Override
        public void onAdImpression() {

        }

        @Override
        public void onAdClicked() {

        }

        @Override
        public void onAdClosed() {

        }

    };

    void setNotLoading() {
        if (mActiveRequest != null) {
            if (!mActiveRequest.isCanceled()) {
                mActiveRequest.cancel();
            }
            mActiveRequest = null;
        }
    }

    @Nullable
    Activity getContextOrDestroy() {
        final Activity context = mContextRef.get();
        if (context == null) {
            destroy();
            Logger.d("Weak reference to Context in FilexInteristitial became null.");
        }
        return context;
    }


    public void destroy() {
        mContextRef.clear();
        setNotLoading();
        mInternalAdLoader = null;
        mAdListener = EMPTY_AD_LISTENER;
        mEventReceiver.unregister(mEventReceiver);
        mEventReceiver = null;
    }

    @Override
    public void onInterstitialFailed() {
    }

    @Override
    public void onInterstitialShow() {
        mAdListener.onAdImpression();
    }

    @Override
    public void onInterstitialDismissed() {
        mAdListener.onAdClosed();
    }

    @Override
    public void onInterstitialClicked() {
        mAdListener.onAdClicked();
    }
}
